package com.cwx.mychat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cwx.mychat.config.AppConfig;
import com.cwx.mychat.entity.constant.CodeConstant;
import com.cwx.mychat.entity.constant.FileSettingConstant;
import com.cwx.mychat.entity.constant.SysSettingConstant;
import com.cwx.mychat.entity.dto.TokenUserInfoDto;
import com.cwx.mychat.entity.enums.*;
import com.cwx.mychat.entity.po.*;
import com.cwx.mychat.entity.vo.GroupInfoVo;
import com.cwx.mychat.entity.vo.MessageSendVo;
import com.cwx.mychat.entity.vo.UserInfoVO;
import com.cwx.mychat.exception.BusinessException;
import com.cwx.mychat.mappers.ChatMessageMapper;
import com.cwx.mychat.mappers.ChatSessionMapper;
import com.cwx.mychat.mappers.ChatSessionUserMapper;
import com.cwx.mychat.mappers.GroupInfoMapper;
import com.cwx.mychat.service.GroupInfoService;
import com.cwx.mychat.service.GroupNoticeService;
import com.cwx.mychat.service.UserContactService;
import com.cwx.mychat.service.UserInfoService;
import com.cwx.mychat.utils.R;
import com.cwx.mychat.utils.common.CommonUtil;
import com.cwx.mychat.utils.minio.MinioUtil;
import com.cwx.mychat.utils.redis.RedisComponent;
import com.cwx.mychat.utils.stringUtils.StringUtil;
import com.cwx.mychat.utils.threadLocal.ThreadLocalUtil;
import com.cwx.mychat.websocket.context.ChannelContextUtil;
import com.cwx.mychat.websocket.message.SendMessageHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

@Service
@Slf4j
public class GroupInfoServiceImpl extends ServiceImpl<GroupInfoMapper, GroupInfo> implements GroupInfoService {


    @Autowired
    private RedisComponent redisComponent;

    @Autowired
    private UserContactService userContactService;


    @Autowired
    private MinioUtil minioUtil;

    @Autowired
    private ChatSessionUserMapper chatSessionUserMapper;

    @Autowired
    private ChatMessageMapper chatMessageMapper;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private ChatSessionMapper chatSessionMapper;

    @Autowired
    private SendMessageHandler sendMessageHandler;

    @Autowired
    private ChannelContextUtil channelContextUtil;

    @Autowired
    private GroupNoticeService groupNoticeService;



    @Override
    @Transactional
    public R saveGroup(GroupInfo groupInfo, MultipartFile file) throws BusinessException {
        //获取当前用户
        TokenUserInfoDto tokenUserInfoDto = CommonUtil.getSecurityContext();
        //创建时间
        Date date = new Date();
        //查询用户创建了多少给群聊
        Long count = this.baseMapper.selectCount(new LambdaQueryWrapper<GroupInfo>().eq(GroupInfo::getGroupOwnerId, groupInfo.getGroupOwnerId()));
        SysSettingConstant sysSetting = redisComponent.getSysSetting();
        if(count > sysSetting.getMaxGroupCount()){
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_CREATE_COUNT);
        }
        if(file == null){
            throw new BusinessException(ExceptionBizCodeEnum.ACCOUNT_FILE_NO_UPLOAD);
        }
        if(file.getSize() > sysSetting.getMaxImageSize() * FileSettingConstant.FILE_SIZE_MB
                || !ArrayUtils.contains(FileSettingConstant.IMAGE_SUFFIX_LIST, StringUtil.getFileSuffix(file.getOriginalFilename()).toLowerCase())){
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_AVATAR_ERROR);
        }

        groupInfo.setCreateTime(date);
        groupInfo.setGroupId(StringUtil.getGroupId());

        //保存到数据库和minio中
        String imageUrl = minioUtil.uploadFile(file, FileSettingConstant.AVATAR_CATALOGUE);
        System.out.println(imageUrl);
        groupInfo.setGroupAvatar(imageUrl);
        groupInfo.setStatus(GroupStatusEnum.NORMAL.getStatus());
        groupInfo.setMaxNumber(sysSetting.getMaxGroupMemberCount());
        groupInfo.setBeautifulNumber(StringUtil.getRandomNumber(CodeConstant.INTEGER_11));
        groupInfo.setCurrentNumber(1);
        this.baseMapper.insert(groupInfo);

        //将群组添加为联系人
        UserContact userContact = new UserContact();
        userContact.setStatus(UserContactStatusEnum.FRIEND.getStatus());
        userContact.setContactId(groupInfo.getGroupId());
        userContact.setContactType(UserContactTypeEnum.GROUP.getType());
        userContact.setUserId(groupInfo.getGroupOwnerId());
        userContact.setCreateTime(date);
        userContact.setLastUpdateTime(date);
        Long integer1 = userContactService.getBaseMapper().selectCount(new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, groupInfo.getGroupOwnerId())
                .eq(UserContact::getContactId, groupInfo.getGroupId()));
        if(integer1 > 0){
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_EXIST);
        }
        this.userContactService.save(userContact);

        //创建会话
        ChatSessionUser chatSessionUser = new ChatSessionUser();
        chatSessionUser.setContactName(groupInfo.getGroupName());
        chatSessionUser.setContactId(groupInfo.getGroupId());
        chatSessionUser.setUserId(groupInfo.getGroupOwnerId());
        chatSessionUser.setIsAdmin(GroupAdminTypeEnum.IS_ADMIN.getStatus());
        //查询该用户名
        UserInfo byId = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>()
                .select(UserInfo::getNickName, UserInfo::getUserId, UserInfo::getEmail, UserInfo::getPhone)
                .eq(UserInfo::getUserId, groupInfo.getGroupOwnerId()));
        if(byId == null){
            throw new BusinessException(ExceptionBizCodeEnum.NOT_FOUND_ACCOUNT);
        }
        chatSessionUser.setNickName(byId.getNickName());
        chatSessionUser.setSessionId(CommonUtil.getChatSessionIdUser(new String[]{groupInfo.getGroupId(), groupInfo.getGroupOwnerId()}));
        //先查询再增加
        Long integer = chatSessionUserMapper.selectCount(new LambdaQueryWrapper<ChatSessionUser>().eq(ChatSessionUser::getContactId, groupInfo.getGroupId())
                .eq(ChatSessionUser::getUserId, groupInfo.getGroupOwnerId()));
        if(integer > 0) {
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_EXIST);
        }
        chatSessionUserMapper.insert(chatSessionUser);
        //发送消息
        //1. 组装消息
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setMessageType(MessageTypeEnum.GROUP_CREATE.getType());
        chatMessage.setSessionId(chatSessionUser.getSessionId());
        chatMessage.setMessageContent(MessageTypeEnum.GROUP_CREATE.getInitMsg());
        chatMessage.setSendUserId(groupInfo.getGroupId());
        chatMessage.setSendUserNickName(groupInfo.getGroupName());
        chatMessage.setSendTime(date.getTime());
        chatMessage.setContactId(groupInfo.getGroupOwnerId());
        chatMessage.setContactType(UserContactTypeEnum.GROUP.getType());
        chatMessage.setCreateTime(date);
        chatMessage.setStatus(MessageStatusEnum.SEND.getStatus());
        int insert = chatMessageMapper.insert(chatMessage);
        if(insert <= 0){
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_CREATE_FAILED);
        }
        //2 .组装chatSession
        ChatSession chatSession = new ChatSession();
        chatSession.setLastMessage(MessageTypeEnum.GROUP_CREATE.getInitMsg());
        chatSession.setCreateTime(date);
        chatSession.setLastReceiveTime(date.getTime());
        chatSession.setSessionId(chatSessionUser.getSessionId());
        int chatSessionInsert = chatSessionMapper.insert(chatSession);
        if(chatSessionInsert <= 0){
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_CREATE_FAILED);
        }
        //3.发送消息
        MessageSendVo messageSendVo = new MessageSendVo();
        BeanUtils.copyProperties(chatMessage, messageSendVo);
        messageSendVo.setMessageId(chatMessage.getMessageId().toString());
        messageSendVo.setLastMessage(chatSession.getLastMessage());
        messageSendVo.setLastReceiveTime(chatSession.getLastReceiveTime());
        messageSendVo.setSendTime(chatMessage.getSendTime());
        messageSendVo.setMemberCount(groupInfo.getCurrentNumber());
        messageSendVo.setContactName(groupInfo.getGroupName());
        messageSendVo.setContactId(groupInfo.getGroupId());
        messageSendVo.setAvatar(groupInfo.getGroupAvatar());
        messageSendVo.setSendUserId(tokenUserInfoDto.getUserId());
        messageSendVo.setSendUserNickName(tokenUserInfoDto.getNickName());
        messageSendVo.setMessageType(MessageTypeEnum.GROUP_CREATE.getType());
        //TODO 发送ws消息
        sendMessageHandler.sendMessage(messageSendVo);
        return R.ok("创建群聊成功");
    }

    @Override
    @Transactional
    public void updateGroup(GroupInfo groupInfo) throws BusinessException {

        GroupInfo groupById = this.baseMapper.selectById(groupInfo.getGroupId());
        if(!groupById.getGroupOwnerId().equals(groupInfo.getGroupOwnerId())){
            throw new BusinessException(ExceptionBizCodeEnum.ACCOUNT_ERROR);
        }
        this.baseMapper.updateById(groupInfo);
        //TODO 更新相关表冗余信息

        //TODO 修改群昵称发送ws消息
    }

    @Override
    public R getInfoById(String groupId) throws BusinessException {
        //获取用户信息
        TokenUserInfoDto tokenUserInfoDto = CommonUtil.getSecurityContext();
        log.info("获取用户信息...{}", tokenUserInfoDto);
        UserContact userContact = userContactService.getOne(new LambdaQueryWrapper<UserContact>()
                .eq(UserContact::getUserId, tokenUserInfoDto.getUserId())
                .eq(UserContact::getContactId, groupId));
        if(userContact == null || userContact.getStatus().equals(UserContactStatusEnum.NOT_FRIEND.getStatus())){
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_NOT_EXIST);
        }
        GroupInfo groupInfo = this.getById(groupId);
        if(groupInfo == null || groupInfo.getStatus().equals(GroupStatusEnum.DISSOLVE.getStatus())){
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_NOT_EXIST);
        }
        //获取成员数量
        Long memberCount = userContactService.getBaseMapper().selectCount(new LambdaQueryWrapper<UserContact>()
                .eq(UserContact::getContactId, groupId));
        groupInfo.setMemberCount(memberCount.intValue());
        return R.ok().put(CodeConstant.RESULT_MSG, groupInfo);

    }

    @Override
    public R getUserAndGroupList(TokenUserInfoDto tokenUserInfoDto) {

        //查询与用户有关的所有群聊
        String userId = tokenUserInfoDto.getUserId();
        List<GroupInfo> groupInfos = this.baseMapper.selectList(new LambdaQueryWrapper<GroupInfo>().eq(GroupInfo::getGroupOwnerId, userId));

        return R.ok();
    }

    @Override
    @Transactional
    public R deleteGroup(String groupId) throws BusinessException {
        //判断是否为创建群聊者,防止恶意删除
        GroupInfo groupInfo = this.baseMapper.selectById(groupId);
        TokenUserInfoDto tokenUserInfoDto = CommonUtil.getSecurityContext();
        if(!groupInfo.getGroupOwnerId().equals(tokenUserInfoDto.getUserId())){
            //无权删除q群组
            throw new BusinessException(ExceptionBizCodeEnum.NO_PERMISSION_DELETE_GROUP);
        }
        try{
            //1. 删除群组表
            this.baseMapper.deleteById(groupId);
            //2. 删除联系表
            userContactService.removeById(groupId);
            //删除我的session表
            chatSessionUserMapper.delete(new LambdaQueryWrapper<ChatSessionUser>().eq(ChatSessionUser::getUserId, groupInfo.getGroupOwnerId()).eq(ChatSessionUser::getContactId, groupId));
        }catch (Exception e){
            log.error("群组删除失败", e);
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_DELETE_FAILED);
        }

        //3. 通知群里人员解散群聊
        MessageSendVo messageSendVo = new MessageSendVo();
        messageSendVo.setMessageType(MessageTypeEnum.DISSOLUTION_GROUP.getType());
        messageSendVo.setMessageContent(MessageTypeEnum.DISSOLUTION_GROUP.getInitMsg());
        messageSendVo.setSendUserId(tokenUserInfoDto.getUserId());
        messageSendVo.setContactId(groupInfo.getGroupId());
        sendMessageHandler.sendMessage(messageSendVo);
        return R.ok();
    }

    @Override
    public R getGroupAllInfoById(String groupId, String userId) throws BusinessException {
        List<String> groupIds = Arrays.asList(groupId.split(","));
        List<GroupInfoVo> groupInfoVos = this.baseMapper.selectByIds(groupIds, userId);
        if(groupInfoVos == null || groupInfoVos.size() == 0){
            throw new BusinessException(ExceptionBizCodeEnum.GROUP_NOT_EXIST);
        }
        GroupInfoVo groupInfoVo = groupInfoVos.get(0);
        //设置备注
        groupInfoVo.setRemark(userContactService.getRemark(groupInfoVo.getGroupId(), groupInfoVo.getRemark()));
        //统计在线人数
        Integer groupMemberById = channelContextUtil.getGroupMemberById(groupId);
        groupInfoVo.setMemberCount(groupMemberById);
        //查询最新一条群公告
        GroupNotice groupNotice = groupNoticeService.getOne(new LambdaQueryWrapper<GroupNotice>().eq(GroupNotice::getGroupId, groupId).orderByDesc(GroupNotice::getPubTime).last("limit 1"));
        if(groupNotice != null){
            groupInfoVo.setGroupNotice(groupNotice);
        }
        //查询群成员
        List<UserInfoVO> userInfoVos = this.baseMapper.selectMemberList(groupInfoVo.getGroupId());
        groupInfoVo.setGroupMemberDistribution(userInfoVos);
        return R.ok().put(CodeConstant.RESULT_MSG, groupInfoVo);
    }
}
